#include "Model.h"
#include "MatUtil.h"

Model::Model()
{
	CvarSystem& cvars = CvarSystem::getInstance();
	_transformType = cvars.addCvar("m_transform_type", MODEL_FRAME);
}

void Model::translate(float x, float y, float z)
{
	Mat4 T;
	if (_transformType->getValueI() == WORLD_FRAME) {
		T = MatUtil::translate(x, y, z);
	}
	else {
		Vec4 xx = _rotations * Vec4(x, 0.0f, 0.0f, 1.0f);
		Vec4 yy = _rotations * Vec4(0.0f, y, 0.0f, 1.0f);
		Vec4 zz = _rotations * Vec4(0.0f, 0.0f, z, 1.0f);
		Vec4 v = xx + yy + zz;

		T = MatUtil::translate(v.x, v.y, v.z);
	}

	_translations = T * _translations;
	_transform = T * _transform;
}

void Model::scale(float x, float y, float z)
{
	Mat4 S = MatUtil::scale(x, y, z);
	Mat4 T = MatUtil::inverseTranlations(_translations);
	Mat4 TI = _translations;

	Mat4 M;
	if (_transformType->getValueI() == WORLD_FRAME) {
		M = S;
	}
	else {
		Mat4 R = MatUtil::inverseRotations(_rotations);
		Mat4 RI = _rotations;

		M = RI * S * R;
	}

	_transform = TI * M * T * _transform;
}

void Model::rotate(float x, float y, float z)
{
	Mat4 T = MatUtil::inverseTranlations(_translations);
	Mat4 TI = _translations;
	
	Mat4 R;
	if (_transformType->getValueI() == WORLD_FRAME) {
		R = MatUtil::rotate(x, y, z);
	}
	else {
		Vec4 xx = _rotations * Vec4(1.0f, 0.0f, 0.0f, 1.0f);
		Vec4 yy = _rotations * Vec4(0.0f, 1.0f, 0.0f, 1.0f);
		Vec4 zz = _rotations * Vec4(0.0f, 0.0f, 1.0f, 1.0f);

		R = Mat4();
		R *= MatUtil::rotateArbitraryAxis(Vec3(xx.x, xx.y, xx.z), x);
		R *= MatUtil::rotateArbitraryAxis(Vec3(yy.x, yy.y, yy.z), y);
		R *= MatUtil::rotateArbitraryAxis(Vec3(zz.x, zz.y, zz.z), z);
	}	

	_rotations = R * _rotations;
	_transform = TI * R * T * _transform;
}

Vec3 Model::getPosition()
{
	Vec4 posh = _translations * Vec4(0.0f, 0.0f, 0.0f, 1.0f);
	return Vec3(posh.x, posh.y, posh.z);
}